package com.dingup.provider.controller.wx;

import com.alibaba.fastjson.JSONObject;
import com.dingup.api.Util.JwtTokenUtil;
import com.dingup.api.Util.PasswordUtil;
import com.dingup.api.Util.RedisUtils;
import com.dingup.api.base.HttpResContent;
import com.dingup.api.model.sys.*;
import com.dingup.provider.mapper.*;
import com.dingup.provider.service.sys.LoadUserPermissionService;
import com.dingup.provider.service.sys.SysPermissionService;
import com.dingup.provider.service.sys.SysUserService;
import com.dingup.provider.util.CookieUtil;
import com.dingup.util.GCookieUtil;
import com.suyeer.basic.util.BHttpResUtil;
import com.suyeer.basic.util.BLogUtil;
import com.suyeer.cache.RedisUtil;
import com.suyeer.fastwechat.util.FwUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

import static com.dingup.api.base.BaseUtil.*;
import static com.dingup.api.enums.ThirdPartyTypeEnum.WEI_XIN;
import static com.dingup.provider.util.ConstUtil.*;

/**
 * Created by jun on 2018/8/7.
 */
@Controller
@RequestMapping("/wx")
public class WxController {

    private final String URL_GET_WX_USER_INFO_FORM_IBT = "https://ibt.topschool.com/wx/get_wx_user_info.do";
    @Autowired
    SysPermissionService sysPermissionService;
    @Autowired
    LoadUserPermissionService loadUserPermissionService;
    @Autowired
    private SysWxOpenIdInfoMapper sysWxOpenIdInfoMapper;
    @Autowired
    private SysWxUserMapper sysWxUserMapper;
    @Autowired
    private ThirdPartyUserInfoMapper thirdPartyUserInfoMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysUserBindInfoMapper sysUserBindInfoMapper;

    @RequestMapping(value = "/get_wx_config.do", method = RequestMethod.POST)
    public void getWxConfig(@RequestParam(PARAM_URL) String url,
                            HttpServletRequest request,
                            HttpServletResponse response) {
        HttpResContent<JSONObject> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("获取微信分享配置参数");
        try {
            // check.
            checkParam(PARAM_URL, url);
            // do.
            BLogUtil.info("获取微信分享配置参数URL: {}, AccessToken: {}", url, FwUtil.getAccessToken());
            JSONObject retObj = FwUtil.getJsSdkConfig(url);
            saveSuccessMsgAndData(hrc, retObj);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    @RequestMapping(value = "/delete_cookie", method = RequestMethod.GET)
    public void deleteCookie(HttpServletRequest request,
                             HttpServletResponse response) {
        HttpResContent<Boolean> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("删除 Cookie");
        try {
            CookieUtil.delCookie(response, COOKIE_ITEM_WX_USER_INFO);
            saveSuccessMsgAndData(hrc, true);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    @RequestMapping(value = "/check_author", method = RequestMethod.GET)
    public String checkAuthor(@RequestParam(PARAM_OPENID) String openid,
                              @RequestParam(PARAM_ORIGINAL_URL) String originalUrl,
                              HttpServletRequest request,
                              HttpServletResponse response) {
        HttpResContent<Boolean> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("检查授权");
        try {
            // check.
            checkParam(PARAM_OPENID, openid);
            checkParam(PARAM_ORIGINAL_URL, originalUrl);
            // do.
            if (!sysWxOpenIdInfoMapper.existOpenId(openid)) {
                addWxUser(openid);
            }
            Cookie cookie = GCookieUtil.getCookieByName(request, COOKIE_ITEM_WX_USER_INFO);
            CookieUtil.addCookie(response, COOKIE_ITEM_WX_USER_INFO, openid, DEFAULT_COOKIE_AGE);
            saveSuccessMsgAndData(hrc, true);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        }
        return "redirect:" + originalUrl;
    }

    @RequestMapping(value = "/get_wx_user_info.do", method = RequestMethod.POST)
    public void getWxUserInfo(@RequestParam(PARAM_USER_ID) String userId,
                              HttpServletRequest request,
                              HttpServletResponse response) {
        HttpResContent<JSONObject> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("获取微信用户信息");
        try {
            // check.
            checkParam(PARAM_USER_ID, userId);
            // do.
            JSONObject retObj = new JSONObject();
            String openid = CookieUtil.getOpenid(request);
            SysWxOpenIdInfo sysWxOpenIdInfo = sysWxOpenIdInfoMapper.getByOpenId(openid);
            if (sysWxOpenIdInfo == null) {
                throw new Exception("获取微信用户数据失败!");
            }
            String unionId = sysWxOpenIdInfo.getUnionId();
            SysWxUser sysWxUser = sysWxUserMapper.getByUnionId(unionId);
            retObj.put(KEY_NICK_NAME, sysWxUser.getNickName());
            retObj.put(KEY_AVATAR_URL, sysWxUser.getAvatarUrl());
            retObj.put(KEY_IF_BIND, false);
            retObj.put(KEY_IF_BIND_CURRENT_ACCOUNT, false);
            ThirdPartyUserInfo thirdPartyUserInfo = thirdPartyUserInfoMapper.getByThirdPartyUserIdAndThirdPartyType(
                    unionId, WEI_XIN);
            if (thirdPartyUserInfo != null) {
                retObj.put(KEY_IF_BIND, true);
                retObj.put(KEY_USER_NAME, sysUserService.getUserNameById(thirdPartyUserInfo.getUserId()));
                retObj.put(KEY_IF_BIND_CURRENT_ACCOUNT, thirdPartyUserInfo.getUserId().equals(userId));
            }
            saveSuccessMsgAndData(hrc, retObj);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    @RequestMapping(value = "/check_bind.do", method = RequestMethod.POST)
    public void checkBind(@RequestParam(PARAM_USER_ID) String userId,
                          HttpServletRequest request,
                          HttpServletResponse response) {
        HttpResContent<JSONObject> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("检查绑定微信");
        try {
            // check.
            checkParam(PARAM_USER_ID, userId);
            // do.
            JSONObject retObj = new JSONObject();
            retObj.put(KEY_IF_BIND, false);
            retObj.put(KEY_NICK_NAME, StringUtils.EMPTY);
            retObj.put(KEY_AVATAR_URL, StringUtils.EMPTY);
            ThirdPartyUserInfo thirdPartyUserInfo = thirdPartyUserInfoMapper.getByUserIdAndThirdPartyType(userId, WEI_XIN);
            if (thirdPartyUserInfo != null) {
                String unionId = thirdPartyUserInfo.getThirdPartyUserId();
                SysWxUser sysWxUser = sysWxUserMapper.getByUnionId(unionId);
                retObj.put(KEY_IF_BIND, true);
                retObj.put(KEY_NICK_NAME, sysWxUser.getNickName());
                retObj.put(KEY_AVATAR_URL, sysWxUser.getAvatarUrl());
            }
            String info = String.format("%s:Success!", hrc.getFuncDes());
            hrc.fillData(HttpStatus.SC_OK, info, retObj);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    @RequestMapping(value = "/bind.do", method = RequestMethod.POST)
    public void bind(@RequestParam(PARAM_USER_ID) String userId,
                     @RequestParam(value = PARAM_IF_CHANGE_WX, required = false) Boolean ifChangeWx,
                     HttpServletRequest request,
                     HttpServletResponse response) {
        HttpResContent<Boolean> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("绑定微信");
        try {
            // check.
            checkParam(PARAM_USER_ID, userId);
            // do.
            ifChangeWx = (ifChangeWx == null ? false : ifChangeWx);
            String openid = CookieUtil.getOpenid(request);
            SysWxOpenIdInfo sysWxOpenIdInfo = sysWxOpenIdInfoMapper.getByOpenId(openid);
            if (sysWxOpenIdInfo == null) {
                throw new Exception("获取微信用户数据失败!");
            }
            String unionId = sysWxOpenIdInfo.getUnionId();
            ThirdPartyUserInfo thirdPartyUserInfo1 = thirdPartyUserInfoMapper.getByUserIdAndThirdPartyType(
                    userId, WEI_XIN
            );
            ThirdPartyUserInfo thirdPartyUserInfo2 = thirdPartyUserInfoMapper.getByThirdPartyUserIdAndThirdPartyType(
                    unionId, WEI_XIN
            );
            if (thirdPartyUserInfo2 != null) {
                throw new Exception("当前微信已绑定其他系统账号!");
            }
            ifChangeWx = (thirdPartyUserInfo1 != null);
            if (ifChangeWx) {
                thirdPartyUserInfo1.setThirdPartyUserId(unionId);
                if (!thirdPartyUserInfoMapper.updateThirdPartyUserId(thirdPartyUserInfo1)) {
                    throw new Exception("更换微信失败!");
                }
            } else {
                if (thirdPartyUserInfo1 != null) {
                    throw new Exception("当前系统账号已绑定其他账号!");
                }
                ThirdPartyUserInfo thirdPartyUserInfo = new ThirdPartyUserInfo();
                thirdPartyUserInfo.setUserId(userId);
                thirdPartyUserInfo.setThirdPartyUserId(unionId);
                thirdPartyUserInfo.setThirdPartyType(WEI_XIN);
                if (!thirdPartyUserInfoMapper.add(thirdPartyUserInfo)) {
                    throw new Exception("保存数据失败!");
                }
                SysUser student = new SysUser();
                student.setUserId(userId);
                student.setUserPassword(PasswordUtil.getPassword());
                student.setIfActive(true);
                sysUserMapper.updateByPrimaryKeySelective(student);

            }
            saveSuccessMsgAndData(hrc, true);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    @RequestMapping(value = "/get_parent_wx_info_pass.do", method = RequestMethod.POST)
    public void getParentWxInfo(@RequestParam(PARAM_USER_ID) String userId,
                                HttpServletRequest request,
                                HttpServletResponse response) {
        HttpResContent<JSONObject> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("获取绑定的家长微信信息");
        try {
            // check.
            checkParam(PARAM_USER_ID, userId);
            // do.
            JSONObject retObj = new JSONObject();
            retObj.put(KEY_IF_BIND, false);
            List<SysUserBindInfo> sysUserBindInfoList = sysUserBindInfoMapper.listByUserId(userId);
            if (sysUserBindInfoList.size() > 0) {
                String unionId = sysUserBindInfoList.get(0).getParentWxUnionId();
                SysWxUser sysWxUser = sysWxUserMapper.getByUnionId(unionId);
                retObj.put(KEY_IF_BIND, true);
                retObj.put(KEY_NICK_NAME, sysWxUser.getNickName());
                retObj.put(KEY_AVATAR_URL, sysWxUser.getAvatarUrl());
            }
            saveSuccessMsgAndData(hrc, retObj);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    @RequestMapping(value = "/bind_parent_wx_pass.do", method = RequestMethod.POST)
    public void bindParentWx(@RequestParam(PARAM_USER_ID) String userId,
                             HttpServletRequest request,
                             HttpServletResponse response) {
        HttpResContent<Boolean> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("绑定家长微信");
        try {
            // check.
            checkParam(PARAM_USER_ID, userId);
            // do.
            String openid = CookieUtil.getOpenid(request);
            SysWxOpenIdInfo sysWxOpenIdInfo = sysWxOpenIdInfoMapper.getByOpenId(openid);
            if (sysWxOpenIdInfo == null) {
                throw new Exception("获取微信用户数据失败!");
            }
            String unionId = sysWxOpenIdInfo.getUnionId();
            SysUserBindInfo sysUserBindInfo = new SysUserBindInfo();
            sysUserBindInfo.setUserId(userId);
            sysUserBindInfo.setParentWxUnionId(unionId);
            if (!sysUserBindInfoMapper.add(sysUserBindInfo)) {
                throw new Exception("保存数据失败!");
            }
            saveSuccessMsgAndData(hrc, true);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    /**
     * User: jun
     * Date: 2018/8/8
     * Desc: 微信扫码登录, pc端接口
     */
    @RequestMapping(value = "/save_qr_token_pass.do", method = RequestMethod.POST)
    public void saveQrToken(@RequestParam(PARAM_QR_TOKEN) String qrToken,
                            HttpServletRequest request,
                            HttpServletResponse response) {
        HttpResContent<Boolean> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("保存二维码Token");
        try {
            // check.
            checkParam(PARAM_QR_TOKEN, qrToken);
            // do.
            RedisUtil.set(qrToken, qrToken, 100);
            saveSuccessMsgAndData(hrc, true);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    /**
     * User: jun
     * Date: 2018/8/8
     * Desc: 微信扫码登录, pc端接口
     */
    @RequestMapping(value = "/check_qr_token_pass.do", method = RequestMethod.POST)
    public void checkQrToken(@RequestParam(PARAM_QR_TOKEN) String qrToken,
                             HttpServletRequest request,
                             HttpServletResponse response) {
        HttpResContent<String> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("检查二维码Token状态");
        try {
            // check.
            checkParam(PARAM_QR_TOKEN, qrToken);
            // do.
            String token = StringUtils.EMPTY;
            String userId = RedisUtil.get(qrToken);
            if (userId == null) {
                throw new Exception("二维码已过期");
            }
            if (StringUtils.isNotBlank(userId) && !qrToken.equals(userId)) {
                SysUser sysUser = sysUserMapper.getByUserId(userId);
                List<String> roles = sysPermissionService.getPermissionByUserId(userId);
                token = JwtTokenUtil.createToken(sysUser.getUserAccount(), roles);
                if (StringUtils.isBlank(token)) {
                    throw new Exception("获取Token失败!");
                }
                RedisUtils.getInstance().setUser(sysUser);
                RedisUtils.getInstance().setToken(sysUser.getUserAccount(), token);
                //加载用户的数据权限
                loadUserPermissionService.loadUserDataPermission(sysUser.getUserId());
                //创建cookie
                response.setHeader(JwtTokenUtil.tokenName, token);
            }
            String info = String.format("%s:Success!", hrc.getFuncDes());
            hrc.fillData(HttpStatus.SC_OK, info, token);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    /**
     * User: jun
     * Date: 2018/8/8
     * Desc: 微信扫码登录, 微信端接口, 点击立即登录
     */
    @RequestMapping(value = "/wx_qr_login_pass.do", method = RequestMethod.POST)
    public void wxQrLogin(@RequestParam(PARAM_QR_TOKEN) String qrToken,
                          HttpServletRequest request,
                          HttpServletResponse response) {
        HttpResContent<Boolean> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("微信授权登录");
        try {
            // check.
            checkParam(PARAM_QR_TOKEN, qrToken);
            // do.
            String userId = RedisUtil.get(qrToken);
            if (userId == null) {
                throw new Exception("二维码已过期");
            }
            String openid = CookieUtil.getOpenid(request);
            SysWxOpenIdInfo sysWxOpenIdInfo = sysWxOpenIdInfoMapper.getByOpenId(openid);
            if (sysWxOpenIdInfo == null) {
                throw new Exception("获取微信用户数据失败!");
            }
            String unionId = sysWxOpenIdInfo.getUnionId();
            ThirdPartyUserInfo thirdPartyUserInfo = thirdPartyUserInfoMapper.getByThirdPartyUserIdAndThirdPartyType(
                    unionId, WEI_XIN
            );
            if (thirdPartyUserInfo == null) {
                throw new Exception("当前微信没有绑定系统账号!");
            }
            RedisUtil.set(qrToken, thirdPartyUserInfo.getUserId(), 100);
            saveSuccessMsgAndData(hrc, true);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    /**
     * User: jun
     * Date: 2018/8/7
     * Desc: 添加微信用户信息
     */
    private void addWxUser(String openid) throws Exception {
        JSONObject param = new JSONObject();
        param.put("openid", openid);
        JSONObject ibtRetObj = BHttpResUtil.sendHttpPostRequest(URL_GET_WX_USER_INFO_FORM_IBT, param);
        if (ibtRetObj.getIntValue("code") != 200) {
            throw new Exception("从 IBT 获取微信用户数据失败");
        }
        JSONObject wxUserObj = ibtRetObj.getJSONObject("result");
        String unionId = wxUserObj.getString("unionId");
        String openId = wxUserObj.getString("openid");
        if (!sysWxUserMapper.existUnionId(unionId)) {
            SysWxUser sysWxUser = new SysWxUser();
            sysWxUser.setAvatarUrl(wxUserObj.getString("headImgUrl"));
            sysWxUser.setUnionId(unionId);
            sysWxUser.setNickName(wxUserObj.getString("nickname"));
            sysWxUser.setCity(wxUserObj.getString("city"));
            sysWxUser.setCountry(wxUserObj.getString("country"));
            sysWxUser.setProvince(wxUserObj.getString("province"));
            sysWxUser.setGender(wxUserObj.getString("sex"));
            sysWxUser.setLanguage(wxUserObj.getString("language"));
            sysWxUserMapper.add(sysWxUser);
        }
        if (!sysWxOpenIdInfoMapper.existOpenId(openId)) {
            SysWxOpenIdInfo sysWxOpenIdInfo = new SysWxOpenIdInfo();
            sysWxOpenIdInfo.setUnionId(unionId);
            sysWxOpenIdInfo.setOpenId(openId);
            sysWxOpenIdInfo.setAppid(WX_APP_ID);
            sysWxOpenIdInfoMapper.add(sysWxOpenIdInfo);
        }
    }
}
